# -*- coding: utf-8 -*-
import d_m3u8.utils.m_utils as util
import time
import os
import collections


class M3u8Video():

    def __init__(self):
        self.workpath = "E:/mp4"  # 文件默认下载路径

    def downVideoByM3u8(self, url):
        """
        根据m3u8链接下载视频
        :param url: m3u8链接地址
        :return:
        """
        url = url.strip()
        # 在工作目录下创建子文件夹
        now_time = str(int(time.time()))
        localpath = self.workpath + "/MA_" + now_time  # 设定子文件夹 M3U8ALL
        util.mkDir(localpath)

        # 下载M3U8文件
        t = util.downM3u8(url, localpath + "/index.m3u8")
        if t is not False:
            print("m3u8文件下载成功，正在解析")
            #  因为有的m3u8文件,还需要下载第二个，所以这里获取一下M3U8文件的真实的存放路径
            localpath = t.split("_*_")[1]

            m3u8url = t.split("_*_")[0]
            if ".m3u8" not in m3u8url:
                m3u8url = m3u8url + "/index.m3u8"
            # 把m3u8链接地址保存一下
            util.mkFile(localpath + "/url.txt", "m3u8url=" + m3u8url+"\n")

            #  开始解析此文件,获取所有的ts链接列表
            tslist = util.analysisM3u8File(localpath + "/index.m3u8", t.split("_*_")[0])
            if tslist is None:
                print("m3u8文件解析失败，ts文件为空...")
                return False
            elif ".m3u8" in tslist:
                # todo com后缀名动态解析
                m3u8url = m3u8url.split(".com")[0] + ".com" + tslist
                util.removeFile(localpath + "/index.m3u8")
                t = util.downM3u8(m3u8url, localpath + "/index.m3u8")
                localpath = t.split("_*_")[1]
                tslist = util.analysisM3u8File(localpath + "/index.m3u8", m3u8url.split(".com")[0] + ".com")
            else:
                print("m3u8文件解析成功，开始下载ts文件")

            # 通过m3u8文件判断ts文件是否需要解密
            keyt = util.fileIfDecrypt(localpath+"/index.m3u8")
            if keyt is False:
                print("goodBoy,不需要解密，开始下载...")
                while True:
                    isall = util.downByList(tslist, localpath)
                    if isall is False:
                        s = input("部分ts文件下载失败，无法开始合并文件，是否继续下载？（y/n）")
                        if s is "n":
                            return False
                    else:
                        break
            else:
                print("很遗憾，需要解密")
                key = util.getKey(m3u8url, keyt, localpath)
                if key is False:
                    return False
                else:
                    while True:
                        isall = util.downByList(tslist, localpath, key)
                        if isall is False:
                            s = input("部分ts文件下载失败，无法开始合并文件，是否继续下载？（y/n）")
                            if s is "n":
                                return False
                        else:
                            break
            hb = util.hbFile(localpath)
            if hb is not False:
                util.tsToMp4(hb)
        else:
            print("m3u8文件下载失败")
            return False

    def downVideoByLocalM3u8OrTs(self, tspath):
        """
        根据本地m3u8文件或者ts文件下载视频，常用于继续下载上次未完成的任务
        :param tspath: ts文件存放路径
        :return:
        """
        filelist = os.listdir(tspath)

        #  获取已经下载过得ts文件列表
        list = []
        m3u8url = None
        # tsurl = None
        snum = None
        enum = None
        for f in filelist:
            filepath = os.path.join(tspath, f)  # 拼接路径
            if os.path.isfile(filepath):
                if os.path.splitext(f)[1] == ".txt":
                    f2 = open(tspath + "/url.txt", "r")
                    text = f2.read()
                    if text:
                        for i in text.split("\n"):
                            if "m3u8url=" in i:
                                m3u8url = i.split("m3u8url=")[1]
                            elif "startnum=" in i:
                                snum = i.split("startnum=")[1]
                            elif "endnum=" in i:
                                enum = i.split("endnum=")[1]
                    f2.close()
                elif os.path.splitext(f)[1] == ".m3u8":
                    murl = tspath + "/" + f
                    util.removeFile(murl)
                elif os.path.splitext(f)[1] == ".key":
                    keyurl = tspath + "/" + f
                    util.removeFile(keyurl)
                elif os.path.splitext(f)[1] == ".ts":
                    list.append(f[-9:])

        if len(list) <= 0:
            list = None

        t = util.downM3u8(m3u8url, tspath + "/index.m3u8")
        if t is False:
            print("m3u8文件下载失败")
            return False
        else:
            print("m3u8文件下载成功，正在解析")
            localpath = t.split("_*_")[1]

            #  开始解析此文件,获取所有的ts链接列表
            tslist = util.analysisM3u8File(localpath + "/index.m3u8", t.split("_*_")[0], snum, enum)
            if tslist is None:
                print("ts文件链接获取失败，m3u8地址可能经过私人加密，暂时无法解析...")
                return False
            else:
                print("m3u8文件解析成功，开始下载ts文件")

            # 通过m3u8文件判断ts文件是否需要解密
            keyt = util.fileIfDecrypt(localpath + "/index.m3u8")
            if keyt is False:
                print("goodBoy,不需要解密")
                while True:
                    isall = util.downByList(tslist, localpath, None, list)
                    if isall is False:
                        s = input("部分ts文件下载失败，无法开始合并文件，是否继续下载？（y/n）")
                        if s is "n":
                            return False
                    else:
                        break
            else:
                print("很遗憾需要解密")
                m3u8url = t.split("_*_")[0] + "/index.m3u8"
                key = util.getKey(m3u8url, keyt, localpath)
                if key is False:
                    return False
                else:
                    while True:
                        isall = util.downByList(tslist, localpath, key, list)
                        if isall is False:
                            s = input("部分ts文件下载失败，无法开始合并文件，是否继续下载？（y/n）")
                            if s is "n":
                                return False
                        else:
                            break
            hb = util.hbFile(localpath)
            if hb is not False:
                util.tsToMp4(hb)

    def downSomeVideoByM3u8(self, m3u8url, startnum, endnum):
        m3u8url = m3u8url.strip()
        #  创建目录 M3U8SOME
        path = self.workpath + "/MS_" +str(int(time.time()))
        util.mkDir(path)
        #  下载m3u8文件
        t = util.downM3u8(m3u8url, path+"/index.m3u8")
        if t is not False:
            print("m3u8文件下载成功，正在解析")
            #  因为有的m3u8文件,还需要下载第二个，所以这里获取一下M3U8文件的真实的存放路径
            localpath = t.split("_*_")[1]

            m3u8url = t.split("_*_")[0] + "/index.m3u8"
            # 把m3u8链接地址,开始号，结束号保存一下
            util.mkFile(localpath + "/url.txt", "m3u8url=" + m3u8url + "\nstartnum=" + startnum + "\nendnum=" + endnum)

            #  开始解析此文件,获取所有的ts链接列表
            tslist = util.analysisM3u8File(localpath + "/index.m3u8", t.split("_*_")[0], startnum, endnum)
            if tslist is None:
                print("ts文件链接获取失败，m3u8地址可能经过私人加密，暂时无法解析...")
                return False
            else:
                print("m3u8文件解析成功，开始下载ts文件")

            # 通过m3u8文件判断ts文件是否需要解密
            keyt = util.fileIfDecrypt(localpath + "/index.m3u8")
            if keyt is False:
                print("goodBoy,不需要解密")
                while True:
                    isall = util.downByList(tslist, localpath)
                    if isall is False:
                        s = input("部分ts文件下载失败，无法开始合并文件，是否继续下载？（y/n）")
                        if s is "n":
                            return False
                    else:
                        break
            else:
                print("很遗憾需要解密")
                m3u8url = t.split("_*_")[0] + "/index.m3u8"
                key = util.getKey(m3u8url, keyt, localpath)
                if key is False:
                    return False
                else:
                    while True:
                        isall = util.downByList(tslist, localpath, key)
                        if isall is False:
                            s = input("部分ts文件下载失败，无法开始合并文件，是否继续下载？（y/n）")
                            if s is "n":
                                return False
                        else:
                            break
            hb = util.hbFile(localpath)
            if hb is not False:
                util.tsToMp4(hb)
        else:
            print("m3u8文件下载失败")
            return False

    def downSomeVideoByTs(self, url, startnum, endnum):
        url = url.strip()
        #  创建目录 TS下载
        path = self.workpath + "/TS_" + str(int(time.time()))
        util.mkDir(path)

        m3u8url = url[:url.rfind("/")]+"/index.m3u8"

        util.mkFile(path+"/url.txt", "m3u8url="+m3u8url+"\nstartnum="+startnum+"\nendnum="+endnum)

        while True:
            t = util.downSomeTs(url,startnum,endnum,path)
            if t is False:
                a = input("文件下载不完整，无法开始合并，是否继续下载缺失文件？（y/n）")
                if a is "n":
                    break
            else:
                print("文件下载完毕，开始合并。")
                break
        hb = util.hbFile(path)
        if hb is not False:
            util.tsToMp4(hb)

    def downVideoByMovieName(self, name):
        map = util.getHtmlByName(name)
        if map is not None:
            map2 = collections.OrderedDict()
            num = 0
            for key in map:
                map2[str(num)] = key
                num = num + 1

            print("\n"+"电影编号".rjust(10, ' ')+"电影名称".center(20, ' ') +
                  "影片地址".center(20, ' ')+"影片类型".center(10, ' '))

            for n in map2:
                print((n+":").rjust(13, ' ')+map2[n].split("_")[0].center(20, ' ') +
                      map2[n].split("_")[1].center(20, )+map2[n].split("_")[2].center(10, ' '))

            movienum = input("\n请输入要选择的电影编号： ")
            movieurl = map[map2[movienum]]
            m3u8url = util.getM3u8ByHtml(movieurl)
            self.downVideoByM3u8(m3u8url)
        else:
            return False


if __name__ == "__main__":

    m = M3u8Video()

    print("Hi,朋友")
    print("******************欢迎使用M3U8视频下载软件*******************")
    print("V2.2.3\n")
    print("1. 文件默认存放目录为 E:/mp4，可自行修改")
    print("   每下载一个视频都会在此目录下单独创建子文件")
    print("2. 程序默认生成的配置文件不可随意删除更改")
    print("   否则可能会导致视频下载失败")
    print("3. ts转码mp4需要解码器，放在同级目录")
    print("   下载地址为 https://gitee.com/dancer6666/m3u8/tree/master")
    print("4. 输入一个链接地址以后最好加个空格再回车确认\n")
    while True:
        print("**------------------功能指令说明---------------------**\n")
        print("     0: 电影名下载            （通过电影名搜索下载视频）")
        print("     1: m3u8完整下载          （通过m3u8链接地址下载视频）")
        print("     2: m3u8截取下载          （通过m3u8链接地址以及范围号截取视频）")
        print("     3: ts截取下载            （通过ts链接截取下载，饶过m3u8链接被加密）")
        print("     4: 指定本地路径下载视频    （一般用于继续上次未完成的任务）")
        print("     5: 文件合并              （合并指定目录下的所有ts文件）")
        print("     6: 解密本地ts文件         （如果是多个文件可先合并再解密）")
        print("     7: ts转码Mp4             （需要依赖解码器，且放在本软件同级目录）")
        print("     8: 修改默认存放目录        （软件重启/退出失效）")
        print("     9: 退出                  （人世间最美好的不是相遇，而是重逢）\n")
        print("**---------------小斌出品，必为精品-------------------**")
        zl = input(">>请输入指令号: ")
        if zl is "0":
            name = input("请输入电影名称： ")
            m.downVideoByMovieName(name)
        elif zl is "1":
            m3path = input("请输入m3u8文件的网络链接地址（输入完以后在末尾加一个空格防止直接跳转）： ")
            m.downVideoByM3u8(m3path)
        elif zl is "2":
            m3path = input("请输入m3u8文件的网络链接地址： ")
            snum = input("请指定ts文件名的开始号（6位数字）： ")
            enum = input("请指定ts文件名的结束号（6位数字）： ")
            m.downSomeVideoByM3u8(m3path, snum, enum)
        elif zl is "3":
            m3path = input("请输入ts文件的网络链接地址： ")
            snum = input("请指定ts文件名的开始号（6位数字）： ")
            enum = input("请指定ts文件名的结束号（6位数字）： ")
            m.downSomeVideoByTs(m3path,snum,enum)
        elif zl is "4":
            tspath = input("请输入本地ts文件的存放路径： ")
            m.downVideoByLocalM3u8OrTs(tspath)
        elif zl is "5":
            hbpath = input("请输入所有需要合并文件的所在目录： ")
            util.hbFile(hbpath)
        elif zl is "6":
            m3path = input("请输入ts文件本地存放路径（含文件名）： ")
            print("秘钥一般存放在当前目录 key.key文件")
            key = input("请输入秘钥： ")
            util.decryptLocalTsFile(m3path, key)
        elif zl is "7":
            tspath2 = input("请输入ts文件本地存放路径（含文件名）： ")
            util.tsToMp4(tspath2)
        elif zl is "8":
            path = input("请输入新的路径: ")
            m.workpath = path
            util.mkDir(path)
            print(path + " 创建成功")
        else:
            print("Bye")
            break




